package com.ttl.service;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.crypto.SecureUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.ttl.common.Constants;
import com.ttl.common.enums.LogModuleEnum;
import com.ttl.common.enums.RoleEnum;
import com.ttl.common.system.AsyncTaskFactory;
import com.ttl.entity.User;
import com.ttl.exception.CustomException;
import com.ttl.mapper.UserMapper;
import com.ttl.utils.RedisUtils;
import com.ttl.utils.SaUtils;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class UserService {

    @Resource
    private UserMapper userMapper;


    /**
     * 新增
     */
    public void add(User user) {
        if (ObjectUtil.isEmpty(user.getUsername())) {
            throw new CustomException("账户不能为空");
        }
        if (ObjectUtil.isEmpty(user.getRole())) {
            throw new CustomException("角色不能为空");
        }
        User dbUser = userMapper.selectByUsername(user.getUsername());
        if (dbUser != null) {
            throw new CustomException("账户已存在");
        }
        if (ObjectUtil.isEmpty(user.getPassword())) {
            user.setPassword(securePassword(Constants.DEFAULT_PASSWORD));
        }
        if (ObjectUtil.isEmpty(user.getName())) {
            user.setName(user.getUsername());
        }
        userMapper.insert(user);
    }

    /**
     * 单个删除
     */
    public void deleteById(Integer id) {
        userMapper.deleteById(id);
    }

    /**
     * 批量删除
     */
    public void deleteBatch(List<Integer> ids) {
        for (Integer id : ids) {
            this.deleteById(id);
        }
    }

    /**
     * 更新
     */
    public void updateById(User user) {
        userMapper.updateById(user);
    }

    /**
     * 单个查询
     */
    public User selectById(Integer id) {
        return userMapper.selectById(id);
    }

    /**
     * 查询所有
     */
    public List<User> selectAll(User user) {
        return userMapper.selectAll(user);
    }

    /**
     * 分页查询
     */
    public PageInfo<User> selectPage(User user, Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        List<User> list = userMapper.selectAll(user);
        return PageInfo.of(list);
    }

    /**
     * 密码加密
     */
    private String securePassword(String password) {
        return SecureUtil.md5(password + Constants.PASSWORD_SALT);
    }

    /**
     * 登录
     * 集成Sa-Token
     */
    public User login(User user) {
        String uuid = user.getUuid();
        String captchaKey = Constants.REDIS_KEY_CAPTCHA + uuid;
        String captchaCode = RedisUtils.getCacheObject(captchaKey);
        if (captchaCode == null) {
            throw new CustomException("验证码已失效");
        }
        if (!user.getCode().equals(captchaCode)) {
            throw new CustomException("验证码错误");
        }
        // 验证完成后删除redis缓存
        RedisUtils.deleteObject(captchaKey);
        String username = user.getUsername();
        // 注意：从数据库查询的数据不一定是非null的，如果是null那么就会报 NULLPOINTEXCEPTION
        User dbUser = userMapper.selectByUsername(username);
        if (dbUser == null) {
            throw new CustomException("账号或密码错误");
        }
        //  密码加盐  bug就是代码里面的蛀虫
        String md5Password = securePassword(user.getPassword());
        if (!dbUser.getPassword().equals(md5Password)) {
            throw new CustomException("账号或密码错误");
        }
        // 返回token
        StpUtil.login(dbUser.getId());
        String token = StpUtil.getTokenValue();
        dbUser.setToken(token);

        // 异步记录日志
        AsyncTaskFactory.recordLog(LogModuleEnum.USER.value, "登录", dbUser.getId());
        return dbUser;
    }

    /**
     * 用户注册
     */
    public void register(User user) {
        user.setRole(RoleEnum.USER.name());
        // 加密密码
        user.setPassword(securePassword(user.getPassword()));
        this.add(user);

        // 异步记录日志
        AsyncTaskFactory.recordLog(LogModuleEnum.USER.value, "注册", user.getId());
    }

    /**
     * 修改密码
     */
    public void updatePassword(User user) {
        User dbUser = userMapper.selectByUsername(user.getUsername());
        if (ObjectUtil.isEmpty(dbUser)) {
            throw new CustomException("账户不存在");
        }
        // 获取当前的登录身份  如果是管理员就不校验密码，如果是用户就校验原密码
        User loginUser = SaUtils.getLoginUser();
        if (RoleEnum.USER.name().equals(loginUser.getRole())) {
            String md5Password = securePassword(user.getPassword());
            if (!dbUser.getPassword().equals(md5Password)) {
                throw new CustomException("原密码错误");
            }
        }
        // 加密新密码
        user.setNewPassword(securePassword(user.getNewPassword()));
        // 更新密码
        userMapper.updatePassword(user);

        // 异步记录日志
        AsyncTaskFactory.recordLog(LogModuleEnum.USER.value, "修改密码", loginUser.getId());
    }

}
